﻿using System.Security;

namespace Vanara.PInvoke;

public static partial class Ole32
{
	/// <summary>Represents the trust level of an activatable class.</summary>
	/// <remarks>
	/// <para>Classes can be activated depending on the trust level of the caller and the trust classification of the activatable class.</para>
	/// <para>RegisteredTrustLevel is an alias for this enumeration.</para>
	/// </remarks>
	// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/ne-inspectable-trustlevel typedef enum TrustLevel { BaseTrust,
	// PartialTrust, FullTrust } ;
	[PInvokeData("inspectable.h", MSDNShortId = "75E30E4B-EE5F-41C4-AC22-91D542E920EB")]
	public enum TrustLevel
	{
		/// <summary>The component has access to resources that are not protected.</summary>
		BaseTrust,

		/// <summary>The component has access to resources requested in the app manifest and approved by the user.</summary>
		PartialTrust,

		/// <summary>The component requires the full privileges of the user.</summary>
		FullTrust,
	}

	/// <summary>Provides functionality required for all Windows Runtime classes.</summary>
	/// <remarks><c>IInspectable</c> methods have no effect on COM apartments and are safe to call from user interface threads.</remarks>
	// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nn-inspectable-iinspectable
	[PInvokeData("inspectable.h", MSDNShortId = "0657E51F-D4C0-46C6-927D-B01E54B6846C")]
	[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90")]
	public interface IInspectable
	{
		/// <summary>Gets the interfaces that are implemented by the current Windows Runtime class.</summary>
		/// <param name="iidCount">
		/// <para>Type: <c>ULONG*</c></para>
		/// <para>
		/// The number of interfaces that are implemented by the current Windows Runtime object, excluding the IUnknown and IInspectable implementations.
		/// </para>
		/// </param>
		/// <param name="iids">
		/// <para>Type: <c>IID**</c></para>
		/// <para>
		/// A pointer to an array that contains an IID for each interface implemented by the current Windows Runtime object. The IUnknown
		/// and IInspectable interfaces are excluded.
		/// </para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This function can return the following values.</para>
		/// <list type="table">
		/// <listheader>
		/// <term>Return code</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>S_OK</term>
		/// <term>The HSTRING was created successfully.</term>
		/// </item>
		/// <item>
		/// <term>E_OUTOFMEMORY</term>
		/// <term>Failed to allocate iids.</term>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>Use the <c>GetIids</c> method to discover the interfaces that are implemented by a Windows Runtime object.</para>
		/// <para>A QueryInterface call on any IID in the iids array must succeed.</para>
		/// <para>The caller is responsible for freeing the IID array by using the CoTaskMemFree function.</para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nf-inspectable-iinspectable-getiids HRESULT GetIids( ULONG
		// *iidCount, IID **iids );
		[PreserveSig]
		HRESULT GetIids(out uint iidCount, out SafeCoTaskMemHandle iids);

		/// <summary>Gets the fully qualified name of the current Windows Runtime object.</summary>
		/// <param name="className">
		/// <para>Type: <c>HSTRING*</c></para>
		/// <para>The fully qualified name of the current Windows Runtime object.</para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This function can return the following values.</para>
		/// <list type="table">
		/// <listheader>
		/// <term>Return code</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>S_OK</term>
		/// <term>The className string was created successfully.</term>
		/// </item>
		/// <item>
		/// <term>E_OUTOFMEMORY</term>
		/// <term>Failed to allocate className string.</term>
		/// </item>
		/// <item>
		/// <term>E_ILLEGAL_METHOD_CALL</term>
		/// <term>className refers to a class factory or a static interface.</term>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>Use the <c>GetRuntimeClassName</c> method to retrieve the namespace-qualified name of a Windows Runtime object.</para>
		/// <para>The caller is responsible for freeing the className string by using the WindowsDeleteString function.</para>
		/// <para>The following table shows example class name strings that cold be returned by the <c>GetRuntimeClassName</c> method.</para>
		/// <list type="table">
		/// <listheader>
		/// <term>Example Class Name</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>Fabrikam.Kitchen.IToaster</term>
		/// <term>An interface in the Fabrikam.Kitchen namespace.</term>
		/// </item>
		/// <item>
		/// <term>Fabrikam.Kitchen.Chef</term>
		/// <term>An class in the Fabrikam.Kitchen namespace.</term>
		/// </item>
		/// <item>
		/// <term>Windows.Foundation.Collections.IVector`1&lt;TailspinToys.IStore&gt;</term>
		/// <term>A vector of TailspinToys.IStore interfaces.</term>
		/// </item>
		/// <item>
		/// <term>Windows.Foundation.Collections.IVector`1&lt;Windows.Foundation.Collections.IMapâ€™2&lt;String, TailspinToys.IStore&gt;&gt;</term>
		/// <term>A vector of maps of strings to TailspinToys.IStore interfaces.</term>
		/// </item>
		/// </list>
		/// <para>
		/// The <c>GetRuntimeClassName</c> method provides the most specific type information that the server object guarantees that it
		/// implements. The type name may be a runtime class name, interface group name, interface name, or parameterized interface name.
		/// </para>
		/// <para>
		/// The <c>GetRuntimeClassName</c> method returns <c>E_ILLEGAL_METHOD_CALL</c> if the class name refers to a class factory or a
		/// static interface.
		/// </para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nf-inspectable-iinspectable-getruntimeclassname HRESULT
		// GetRuntimeClassName( HSTRING *className );
		[PreserveSig]
		HRESULT GetRuntimeClassName([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(HStringMarshaler))] out string className);

		/// <summary>Gets the trust level of the current Windows Runtime object.</summary>
		/// <param name="trustLevel">
		/// <para>Type: <c>TrustLevel*</c></para>
		/// <para>The trust level of the current Windows Runtime object. The default is <c>BaseLevel</c>.</para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This method always returns <c>S_OK</c>.</para>
		/// </returns>
		// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nf-inspectable-iinspectable-gettrustlevel HRESULT
		// GetTrustLevel( TrustLevel *trustLevel );
		[PreserveSig]
		HRESULT GetTrustLevel(out TrustLevel trustLevel);
	}

	/// <summary>
	/// Callback interface implemented by components that need to perform special processing of window messages on an ASTA thread.
	/// </summary>
	// https://docs.microsoft.com/en-us/windows/win32/api/imessagedispatcher/nn-imessagedispatcher-imessagedispatcher
	[PInvokeData("imessagedispatcher.h", MSDNShortId = "60FD9084-CC79-48FE-AB26-C8FCB4288851")]
	[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("F5F84C8F-CFD0-4CD6-B66B-C5D26FF1689D")]
	public interface IMessageDispatcher : IInspectable
	{
		/// <summary>Gets the interfaces that are implemented by the current Windows Runtime class.</summary>
		/// <param name="iidCount">
		/// <para>Type: <c>ULONG*</c></para>
		/// <para>
		/// The number of interfaces that are implemented by the current Windows Runtime object, excluding the IUnknown and IInspectable implementations.
		/// </para>
		/// </param>
		/// <param name="iids">
		/// <para>Type: <c>IID**</c></para>
		/// <para>
		/// A pointer to an array that contains an IID for each interface implemented by the current Windows Runtime object. The IUnknown
		/// and IInspectable interfaces are excluded.
		/// </para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This function can return the following values.</para>
		/// <list type="table">
		/// <listheader>
		/// <term>Return code</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>S_OK</term>
		/// <term>The HSTRING was created successfully.</term>
		/// </item>
		/// <item>
		/// <term>E_OUTOFMEMORY</term>
		/// <term>Failed to allocate iids.</term>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>Use the <c>GetIids</c> method to discover the interfaces that are implemented by a Windows Runtime object.</para>
		/// <para>A QueryInterface call on any IID in the iids array must succeed.</para>
		/// <para>The caller is responsible for freeing the IID array by using the CoTaskMemFree function.</para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nf-inspectable-iinspectable-getiids HRESULT GetIids( ULONG
		// *iidCount, IID **iids );
		[PreserveSig]
		new HRESULT GetIids(out uint iidCount, out SafeCoTaskMemHandle iids);

		/// <summary>Gets the fully qualified name of the current Windows Runtime object.</summary>
		/// <param name="className">
		/// <para>Type: <c>HSTRING*</c></para>
		/// <para>The fully qualified name of the current Windows Runtime object.</para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This function can return the following values.</para>
		/// <list type="table">
		/// <listheader>
		/// <term>Return code</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>S_OK</term>
		/// <term>The className string was created successfully.</term>
		/// </item>
		/// <item>
		/// <term>E_OUTOFMEMORY</term>
		/// <term>Failed to allocate className string.</term>
		/// </item>
		/// <item>
		/// <term>E_ILLEGAL_METHOD_CALL</term>
		/// <term>className refers to a class factory or a static interface.</term>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>Use the <c>GetRuntimeClassName</c> method to retrieve the namespace-qualified name of a Windows Runtime object.</para>
		/// <para>The caller is responsible for freeing the className string by using the WindowsDeleteString function.</para>
		/// <para>The following table shows example class name strings that cold be returned by the <c>GetRuntimeClassName</c> method.</para>
		/// <list type="table">
		/// <listheader>
		/// <term>Example Class Name</term>
		/// <term>Description</term>
		/// </listheader>
		/// <item>
		/// <term>Fabrikam.Kitchen.IToaster</term>
		/// <term>An interface in the Fabrikam.Kitchen namespace.</term>
		/// </item>
		/// <item>
		/// <term>Fabrikam.Kitchen.Chef</term>
		/// <term>An class in the Fabrikam.Kitchen namespace.</term>
		/// </item>
		/// <item>
		/// <term>Windows.Foundation.Collections.IVector`1&lt;TailspinToys.IStore&gt;</term>
		/// <term>A vector of TailspinToys.IStore interfaces.</term>
		/// </item>
		/// <item>
		/// <term>Windows.Foundation.Collections.IVector`1&lt;Windows.Foundation.Collections.IMapâ€™2&lt;String, TailspinToys.IStore&gt;&gt;</term>
		/// <term>A vector of maps of strings to TailspinToys.IStore interfaces.</term>
		/// </item>
		/// </list>
		/// <para>
		/// The <c>GetRuntimeClassName</c> method provides the most specific type information that the server object guarantees that it
		/// implements. The type name may be a runtime class name, interface group name, interface name, or parameterized interface name.
		/// </para>
		/// <para>
		/// The <c>GetRuntimeClassName</c> method returns <c>E_ILLEGAL_METHOD_CALL</c> if the class name refers to a class factory or a
		/// static interface.
		/// </para>
		/// </remarks>
		// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nf-inspectable-iinspectable-getruntimeclassname HRESULT
		// GetRuntimeClassName( HSTRING *className );
		[PreserveSig]
		new HRESULT GetRuntimeClassName([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(HStringMarshaler))] out string className);

		/// <summary>Gets the trust level of the current Windows Runtime object.</summary>
		/// <param name="trustLevel">
		/// <para>Type: <c>TrustLevel*</c></para>
		/// <para>The trust level of the current Windows Runtime object. The default is <c>BaseLevel</c>.</para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This method always returns <c>S_OK</c>.</para>
		/// </returns>
		// https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nf-inspectable-iinspectable-gettrustlevel HRESULT
		// GetTrustLevel( TrustLevel *trustLevel );
		[PreserveSig]
		new HRESULT GetTrustLevel(out TrustLevel trustLevel);

		/// <summary>Performs custom dispatching when window messages are available to be dispatched on an ASTA thread.</summary>
		/// <returns>If this method succeeds, it returns <c>S_OK</c>. Otherwise, it returns an <c>HRESULT</c> error code.</returns>
		// https://docs.microsoft.com/en-us/windows/win32/api/imessagedispatcher/nf-imessagedispatcher-imessagedispatcher-pumpmessages
		// HRESULT PumpMessages( );
		[PreserveSig]
		HRESULT PumpMessages();
	}

	/// <summary>
	/// Called by message dispatchers on an ASTA thread after dispatching a windows message to provide an opportunity for short-running
	/// infrastructural COM calls and other high-priority or short-running COM work to be dispatched between messages. This helps to
	/// provide similar responsiveness to these infrastructural calls in an ASTA as in a classic STA, even when there is a long stream of
	/// window messages to be handled.
	/// </summary>
	/// <returns>If this function succeeds, it returns <c>S_OK</c>. Otherwise, it returns an <c>HRESULT</c> error code.</returns>
	/// <remarks>
	/// <para>
	/// This function dispatches any high-priority COM calls or work that are queued on the ASTA thread, then returns. It returns quickly
	/// if there is no work to perform.
	/// </para>
	/// <para>This function silently does nothing when called on non-ASTA threads.</para>
	/// </remarks>
	// https://docs.microsoft.com/en-us/windows/win32/api/messagedispatcherapi/nf-messagedispatcherapi-cohandlepriorityeventsfrommessagepump
	// void CoHandlePriorityEventsFromMessagePump( );
	[DllImport(Lib.Ole32, SetLastError = false, ExactSpelling = true)]
	[PInvokeData("messagedispatcherapi.h", MSDNShortId = "24EA766D-82F8-4E57-AAB8-A06ECE644319")]
	public static extern void CoHandlePriorityEventsFromMessagePump();

	/// <summary>
	/// Registers or unregisters the per-thread message dispatcher that is to be invoked when there are window messages available to
	/// dispatch within COM wait APIs on an ASTA thread. This function is usually called by CoreWindow, but in certain circumstances
	/// other components that need to specialize how messages are dispatched on an ASTA thread can also call this function.
	/// </summary>
	/// <param name="pMessageDispatcher">
	/// If non-null, message dispatcher object to register. This object must also implement IWeakReferenceSource. If null, unregisters
	/// the current message dispatcher.
	/// </param>
	/// <remarks>
	/// <para>
	/// This function is supported only in ASTA threads. An attempt to set the message dispatcher on a non-ASTA thread silently fails
	/// with no side effects.
	/// </para>
	/// <para>An attempt to set an object that does not implement IWeakReferenceSource silently fails with no side effects.</para>
	/// <para>
	/// A call to this function with a valid and non-null pMessageDispatcher parameter registers this object to receive a PumpMessages
	/// callback whenever there are window messages available to dispatch with COM wait APIs on that ASTA thread. A Windows Runtime weak
	/// reference to this object is held, and the object receives callbacks, until the registration is replaced or the ASTA
	/// uninitialized. Each call to this function replaces the previously registered message dispatcher, if any.
	/// </para>
	/// <para>
	/// There is no way to check if a message dispatcher is registered on an ASTA thread or to retrieve a previously registered message
	/// dispatcher. This function should only be called under circumstances where it is known that this will not collide with another
	/// registration, specifically:
	/// </para>
	/// <list type="bullet">
	/// <item>
	/// <term>
	/// In Windows Store app UI threads, this function is called by CoreWindow to register its dispatcher. No other components should
	/// call this function on these threads.
	/// </term>
	/// </item>
	/// <item>
	/// <term>
	/// UI frameworks may support an authoring mode, in which applications are run in the desktop environment and therefore do not have a
	/// CoreWindow in their UI threads. In lieu of CoreWindow support, these UI frameworks may register a message dispatcher on UI
	/// threads to handle special window message processing usually handled by CoreWindow (such as accelerators). It is not required to
	/// call this function if the UI framework has no need for this functionality.
	/// </term>
	/// </item>
	/// <item>
	/// <term>
	/// IAppVisibility browsers are not restricted to the Windows Store app APIs and therefore may have their own custom window message
	/// processing using user32 APIs. However, these applications still have ASTA UI threads as provided by app object, and may register
	/// a message dispatcher to handle this special processing. It is not required to call this function if the browser has no need for
	/// this functionality.
	/// </term>
	/// </item>
	/// </list>
	/// <para>
	/// The case of IAppVisibility browsers requires care to avoid CoreWindow replacing the browser’s message dispatcher. It is assumed
	/// that the browser has no need for CoreWindow’s dispatcher. The browser should call <c>CoSetMessageDispatcher</c> no sooner than
	/// its IViewProvider::Initialize, or, in the case of views that implement IInitializeWithWindowFactory, no sooner than after it has
	/// created a window on the thread.
	/// </para>
	/// </remarks>
	// https://docs.microsoft.com/en-us/windows/win32/api/messagedispatcherapi/nf-messagedispatcherapi-cosetmessagedispatcher void
	// CoSetMessageDispatcher( PMessageDispatcher pMessageDispatcher );
	[DllImport(Lib.Ole32, SetLastError = false, ExactSpelling = true)]
	[PInvokeData("messagedispatcherapi.h", MSDNShortId = "3D6CFE01-8D3D-474E-A7D0-9B129ECD4EEA")]
	public static extern void CoSetMessageDispatcher(IMessageDispatcher? pMessageDispatcher);


	/// <summary>Marshals HSTRING values.</summary>
	/// <seealso cref="ICustomMarshaler"/>
	internal class HStringMarshaler : ICustomMarshaler
	{
		private HStringMarshaler(string cookie)
		{
		}

		/// <summary>Gets the instance.</summary>
		/// <param name="cookie">The cookie.</param>
		/// <returns>A new instance of this class.</returns>
		public static ICustomMarshaler GetInstance(string cookie) => new HStringMarshaler(cookie);

		/// <summary>Performs necessary cleanup of the managed data when it is no longer needed.</summary>
		/// <param name="ManagedObj">The managed object to be destroyed.</param>
		public void CleanUpManagedData(object ManagedObj) { }

		/// <summary>Performs necessary cleanup of the unmanaged data when it is no longer needed.</summary>
		/// <param name="pNativeData">A pointer to the unmanaged data to be destroyed.</param>
		[SecurityCritical]
		public void CleanUpNativeData(IntPtr pNativeData)
		{
			if (pNativeData != IntPtr.Zero)
				WindowsDeleteString(pNativeData);
		}

		/// <summary>Returns the size of the native data to be marshaled.</summary>
		/// <returns>The size in bytes of the native data.</returns>
		public int GetNativeDataSize() => 0;

		/// <summary>Converts the managed data to unmanaged data.</summary>
		/// <param name="ManagedObj">The managed object to be converted.</param>
		/// <returns>Returns the COM view of the managed object.</returns>
		[SecurityCritical]
		public IntPtr MarshalManagedToNative(object ManagedObj)
		{
			var s = ManagedObj?.ToString();
			WindowsCreateString(s, s?.Length ?? 0, out var hstring).ThrowIfFailed();
			return hstring;
		}

		/// <summary>Converts the unmanaged data to managed data.</summary>
		/// <param name="pNativeData">A pointer to the unmanaged data to be wrapped.</param>
		/// <returns>Returns the managed view of the COM data.</returns>
		[SecurityCritical]
		public object MarshalNativeToManaged(IntPtr pNativeData) => (pNativeData == IntPtr.Zero ? null : (string?)WindowsGetStringRawBuffer(pNativeData, out _)) ?? "";

		/// <summary>Creates a new <c>HSTRING</c> based on the specified source string.</summary>
		/// <param name="sourceString">
		/// <para>Type: [in, optional] <c>LPCWSTR</c></para>
		/// <para>
		/// A null-terminated string to use as the source for the new <c>HSTRING</c>. To create a new, empty, or <c>NULL</c> string, pass
		/// <c>NULL</c> for <c>sourceString</c> and 0 for <c>length</c>.
		/// </para>
		/// </param>
		/// <param name="length">
		/// <para>Type: [in] <c>UINT32</c></para>
		/// <para>The length of <c>sourceString</c>, in Unicode characters. Must be 0 if <c>sourceString</c> is <c>NULL</c>.</para>
		/// </param>
		/// <param name="hstring">
		/// <para>Type: [out] <c><c>HSTRING</c>*</c></para>
		/// <para>
		/// A pointer to the newly created <c>HSTRING</c>, or <c>NULL</c> if an error occurs. Any existing content in <c>string</c> is
		/// overwritten. The <c>HSTRING</c> is a standard handle type.
		/// </para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This function can return one of these values.</para>
		/// <list type="table">
		/// <listheader>
		/// <description>Return code</description>
		/// <description>Description</description>
		/// </listheader>
		/// <item>
		/// <description><c>S_OK</c></description>
		/// <description>The [**HSTRING**](/windows/win32/winrt/hstring) was created successfully.</description>
		/// </item>
		/// <item>
		/// <description><c>E_INVALIDARG</c></description>
		/// <description><c>string</c> is <c>NULL</c>.</description>
		/// </item>
		/// <item>
		/// <description><c>E_OUTOFMEMORY</c></description>
		/// <description>Failed to allocate the new [**HSTRING**](/windows/win32/winrt/hstring).</description>
		/// </item>
		/// <item>
		/// <description><c>E_POINTER</c></description>
		/// <description><c>sourceString</c> is <c>NULL</c> and <c>length</c> is non-zero.</description>
		/// </item>
		/// </list>
		/// </returns>
		/// <remarks>
		/// <para>
		/// Use the <c>WindowsCreateString</c> function to allocate a new <c>HSTRING</c>. The Windows Runtime copies <c>string</c> to the
		/// backing buffer of the new <c>HSTRING</c> and manages the buffer lifetime by using a reference count. Call the
		/// WindowsCreateStringReference function to create a <c>fast-pass string</c>, which uses an existing string without copying it.
		/// </para>
		/// <para>
		/// Call the WindowsDeleteString function to de-allocate the <c>HSTRING</c>. Each call to the <c>WindowsCreateString</c> function
		/// must be matched by a call to <c>WindowsDeleteString</c>.
		/// </para>
		/// <para>To create a new, empty, or <c>NULL</c> string, pass <c>NULL</c> for <c>sourceString</c> and 0 for <c>length</c>.</para>
		/// <para>
		/// If <c>sourceString</c> has embedded null characters, the <c>WindowsCreateString</c> function copies all characters to the
		/// terminating null character.
		/// </para>
		/// </remarks>
		// https://learn.microsoft.com/en-us/windows/win32/api/winstring/nf-winstring-windowscreatestring HRESULT WindowsCreateString(
		// PCNZWCH sourceString, UINT32 length, HSTRING *string );
		[PInvokeData("winstring.h", MSDNShortId = "NF:winstring.WindowsCreateString")]
		[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
		[SecurityCritical]
		[SuppressUnmanagedCodeSecurity]
		private static extern HRESULT WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string? sourceString, int length, out IntPtr hstring);

		/// <summary>Decrements the reference count of a string buffer.</summary>
		/// <param name="hstring">
		/// <para>Type: [in] <c>HSTRING</c></para>
		/// <para>
		/// The string to be deleted. If <c>string</c> is a fast-pass string created by WindowsCreateStringReference, or if <c>string</c> is
		/// <c>NULL</c> or empty, no action is taken and <c>S_OK</c> is returned.
		/// </para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>HRESULT</c></para>
		/// <para>This function always returns <c>S_OK</c>.</para>
		/// </returns>
		/// <remarks>
		/// Use the <c>WindowsDeleteString</c> function to de-allocate an <c>HSTRING</c>. Calling <c>WindowsDeleteString</c> decrements the
		/// reference count of the backing buffer, and if the reference count reaches 0, the Windows Runtime de-allocates the buffer.
		/// </remarks>
		// https://learn.microsoft.com/en-us/windows/win32/api/winstring/nf-winstring-windowsdeletestring HRESULT WindowsDeleteString(
		// HSTRING string );
		[PInvokeData("winstring.h", MSDNShortId = "NF:winstring.WindowsDeleteString")]
		[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
		[SecurityCritical]
		[SuppressUnmanagedCodeSecurity]
		private static extern HRESULT WindowsDeleteString(IntPtr hstring);

		/// <summary>Retrieves the backing buffer for the specified string.</summary>
		/// <param name="hstring">
		/// <para>Type: [in, optional] <c>HSTRING</c></para>
		/// <para>An optional string for which the backing buffer is to be retrieved. Can be <c>NULL</c>.</para>
		/// </param>
		/// <param name="length">
		/// <para>Type: [out, optional] <c>UINT32 *</c></para>
		/// <para>
		/// An optional pointer to a <c>UINT32</c>. If <c>NULL</c> is passed for length, then it is ignored. If length is a valid pointer to
		/// a <c>UINT32</c>, and string is a valid <c>HSTRING</c>, then on successful completion the function sets the value pointed to by
		/// length to the number of Unicode characters in the backing buffer for string (including embedded null characters, but excluding
		/// the terminating null). If length is a valid pointer to a <c>UINT32</c>, and string is <c>NULL</c>, then the value pointed to by
		/// length is set to 0.
		/// </para>
		/// </param>
		/// <returns>
		/// <para>Type: <c>PCWSTR</c></para>
		/// <para>
		/// A pointer to the buffer that provides the backing store for <c>string</c>, or the empty string if <c>string</c> is <c>NULL</c> or
		/// the empty string.
		/// </para>
		/// </returns>
		/// <remarks>
		/// <para>Use the <c>WindowsGetStringRawBuffer</c> function to obtain a pointer to the backing buffer of an <c>HSTRING</c>.</para>
		/// <para>Don't change the contents of the bufferâan <c>HSTRING</c> is required to be immutable.</para>
		/// </remarks>
		// https://learn.microsoft.com/en-us/windows/win32/api/winstring/nf-winstring-windowsgetstringrawbuffer PCWSTR
		// WindowsGetStringRawBuffer( HSTRING string, UINT32 *length );
		[PInvokeData("winstring.h", MSDNShortId = "NF:winstring.WindowsGetStringRawBuffer")]
		[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
		[SecurityCritical]
		[SuppressUnmanagedCodeSecurity]
		private static extern StrPtrUni WindowsGetStringRawBuffer(IntPtr hstring, out uint length);
	}
}